'''
js逆向
'''
import time
from urllib.parse import urlparse

import requests
import json
from bs4 import BeautifulSoup
import execjs
import re

from matplotlib.font_manager import json_load

headers = {
    'authority': 'manatuku.com',
    'method': 'GET',
    'path': '/payments/new',
    'scheme': 'https',
    'accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7',
    'accept-encoding': 'gzip, deflate, br, zstd',
    'accept-language': 'zh-CN,zh;q=0.9',
    'cache-control': 'max-age=0',
    'cookie': '_ga=GA1.2.309142006.1762075975; _ga_5E5M0SZ3LV=GS2.2.s1762075976$o1$g1$t1762077093$j60$l0$h0; aws-waf-token=dbdd6af8-cca7-402f-a6a9-286ec762acee:AQoAuIJKw85AAAAA:p3iGXkQXk7g+aVtSLfOx89tjIOSuIZBM0zUF1gv3Ztav9dB/HaCWMIQVrsySOHcVOgELaBtmwi+K/cm7pZQIm1y+oWrUdERu5Ju9QNEhS4yfOtGiGW2eXNsaxbq98RnZo8m6wzswMnmrxyyb5QDyItMKWp7L4NqpRZihd8I05ICly0Wrw7b6qdaVFvgfyADlI18TFR1kL/7ZTkuK/jrWI5WUtuqtjce8Y/+WqaytLkPFG+/f/tDmsKulRlK5eWa2f6LvIZLBnU1aOVCk',
    'priority': 'u=0, i',
    'referer': 'https://manatuku.com/payments/new',
    'sec-ch-ua': '"Chromium";v="142", "Google Chrome";v="142", "Not_A Brand";v="99"',
    'sec-ch-ua-mobile': '?0',
    'sec-ch-ua-platform': '"Windows"',
    'sec-fetch-dest': 'document',
    'sec-fetch-mode': 'navigate',
    'sec-fetch-site': 'same-origin',
    'sec-fetch-user': '?1',
    'upgrade-insecure-requests': '1',
    'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36'
}
target_url = "https://manatuku.com/payments/new"
captcha = "https://api.capsolver.com/createTask"
captcha_key = "CAP-147149A8FD7E82B0A83BCD2E317C51AB2D5060780317C5C0488E4DBBFF596609"
api_endpoint = "https://api.captcha.com/createTask"
aws_key = "83c6f45a60b4b202f76bb88096ce0bcc"
api_result = "https://api.captcha.com/getTaskResult"
sign_up = "https://manatuku.com/customers/sign_up"

def deobfuscate_js(js_code):
    """
    尝试反混淆 JavaScript 代码
    """
    # 提取十六进制字符串
    hex_pattern = r'0x[0-9a-fA-F]+'
    hex_values = re.findall(hex_pattern, js_code)

    # 提取变量名模式
    var_pattern = r'var\s+(_0x[0-9a-fA-F]+)'
    variables = re.findall(var_pattern, js_code)

    print(f"找到 {len(hex_values)} 个十六进制值")
    print(f"找到 {len(variables)} 个混淆变量")

    # 尝试解码十六进制字符串
    decoded_strings = []
    for hex_val in hex_values[:10]:  # 只显示前10个
        try:
            # 将十六进制转换为十进制
            dec_val = int(hex_val, 16)
            # 如果值在可打印ASCII范围内，尝试显示
            if 32 <= dec_val <= 126:
                decoded_strings.append(f"{hex_val} -> '{chr(dec_val)}'")
        except:
            pass

    return {
        'hex_values': hex_values,
        'variables': variables,
        'decoded_samples': decoded_strings
    }

def extract_aws_waf_info(html_content):
    """
    从 HTML 中提取 AWS WAF 挑战相关信息
    """
    soup = BeautifulSoup(html_content, 'html.parser')

    result = {
        'goku_props': None,
        'challenge_js_url': None,
        'script_functions': [],
        'captcha_url': None,
    }

    # 获取所有 script 标签
    scripts = soup.find_all('script')

    for i, script in enumerate(scripts):
        # 检查是否有 src 属性（外部脚本）
        if script.get('src'):
            src = script.get('src')
            if 'challenge.js' in src:
                result['challenge_js_url'] = src
                print(f"找到 challenge.js: {src}")
            if 'captcha.js' in src:
                result['captcha_url'] = src
        # 检查脚本内容
        if script.string:
            content = script.string.strip()

            # 提取 window.gokuProps
            if 'window.gokuProps' in content:
                print(f"在脚本 {i} 中找到 gokuProps")

                # 方法1: 使用正则表达式提取对象
                goku_match = re.search(r'window\.gokuProps\s*=\s*(\{.*?\});', content, re.DOTALL)
                if goku_match:
                    try:
                        # 注意：这里需要安全地处理，因为可能是 JavaScript 对象而不是纯 JSON
                        goku_str = goku_match.group(1)

                        # 清理 JavaScript 对象格式（处理可能的尾随逗号等）
                        goku_str = re.sub(r',\s*}', '}', goku_str)  # 修复尾随逗号
                        goku_str = re.sub(r',\s*]', ']', goku_str)

                        # 尝试解析为 JSON
                        goku_props = json.loads(goku_str)
                        result['goku_props'] = goku_props
                        print("成功解析 gokuProps:")
                        for key, value in goku_props.items():
                            print(f"  {key}: {value}")

                    except json.JSONDecodeError as e:
                        print(f"JSON 解析错误: {e}")
                        # 如果 JSON 解析失败，尝试手动提取
                        result['goku_props'] = extract_js_object_manual(content)

            # 提取函数调用信息
            if 'AwsWafIntegration' in content:
                func_calls = re.findall(r'AwsWafIntegration\.(\w+)\([^)]*\)', content)
                if func_calls:
                    result['script_functions'].extend(func_calls)
                    print(f"找到 AWS WAF 集成函数: {func_calls}")

    return result


def extract_js_object_manual(js_content):
    """
    手动提取 JavaScript 对象（当 JSON 解析失败时使用）
    """
    result = {}

    # 查找 gokuProps 对象
    start = js_content.find('window.gokuProps = {')
    if start == -1:
        return result

    start += len('window.gokuProps = ')
    brace_count = 0
    in_string = False
    escape_next = False
    obj_content = []

    for i, char in enumerate(js_content[start:], start):
        if escape_next:
            escape_next = False
            continue

        if char == '\\':
            escape_next = True
        elif char == '"' and not escape_next:
            in_string = not in_string
        elif not in_string:
            if char == '{':
                brace_count += 1
            elif char == '}':
                brace_count -= 1
                if brace_count == 0:
                    obj_content.append(char)
                    break

        if brace_count >= 1:
            obj_content.append(char)

    obj_str = ''.join(obj_content)

    # 尝试用更宽松的方式解析
    try:
        # 替换单引号为双引号
        obj_str = obj_str.replace("'", '"')
        # 处理无引号的属性名
        obj_str = re.sub(r'(\w+):', r'"\1":', obj_str)
        return json.loads(obj_str)
    except:
        # 最后手段：使用正则表达式提取键值对
        return extract_key_value_pairs(obj_str)


def extract_key_value_pairs(js_obj_str):
    """
    使用正则表达式从 JS 对象字符串中提取键值对
    """
    pairs = {}
    # 匹配键值对模式
    pattern = r'(\w+)\s*:\s*"([^"]*)"'
    matches = re.findall(pattern, js_obj_str)

    for key, value in matches:
        pairs[key] = value

    return pairs

def get_api_captcha(img_list: list, questions: list):
    question = "aws:grid:" + ":".join(questions)

    proxies = {'https': 'http://127.0.0.1:7897'}

    query = {
        'clientKey': captcha_key,
        'task': {
            'type': "AwsWafClassification",
            'websiteURL': "https://manatuku.com/payments/new",
            'question': question,
            'images': img_list
        }
    }
    result_json = requests.post(url=captcha, json=query, proxies=proxies, verify=False, timeout=10)
    json_data = json.loads(result_json.text)
    solution = json_data["solution"]
    return solution["objects"]

def get_captcha_aws(req:dict):
    proxies = {'https': 'http://127.0.0.1:7897'}
    query = {
        "clientKey": aws_key,
        "task": {
            "type": "AmazonTaskProxyless",
            "websiteURL": "https://manatuku.com/payments/new",
            "challengeScript": req["challenge_js_url"],
            "captchaScript": req['captcha_url'],
            "websiteKey": req["goku_props"]["key"],
            "context": req["goku_props"]["context"],
            "iv": req["goku_props"]["iv"]
        }
    }
    res = requests.post(url=api_endpoint,json=query,proxies=proxies, verify=False, timeout=10)
    json_data = json.loads(res.text)
    if json_data["taskId"]:
        task_id = json_data["taskId"]
        while True:
           time.sleep(2)

           data = {
                "clientKey": aws_key,
                "taskId": task_id
            }
           task_res = requests.post(url=api_result,json=data,proxies=proxies, verify=False, timeout=10)
           if "processing" in task_res.text:
               continue

           elif "errorDescription" in task_res.text:
               return None
           else:
               json_data = json.loads(task_res.text)
               solution = json_data["solution"]
               return solution
    return None


def split_url(url):
    # 解析URL
    parsed = urlparse(url)

    # 获取域名部分
    domain = parsed.netloc

    # 获取路径和查询参数部分
    path_and_query = parsed.path
    if parsed.query:
        path_and_query += '?' + parsed.query

    return domain, path_and_query

def get_human_validate():
    proxies = {'https': 'http://127.0.0.1:7897'}
    response = requests.Session().get(target_url, proxies=proxies, headers=headers, verify=False)
    if response.status_code == 202 or "challenge" in response.text:
        results = extract_aws_waf_info(response.text)
        if results["challenge_js_url"] is not None:
            challenge_js_url:str = results["challenge_js_url"]
            challenge_js_url = challenge_js_url.strip()
            if results['captcha_url'] is not None:
                captcha_js_ur = results['captcha_url']
                results['captcha_url'] = captcha_js_ur
            else:
                captcha_js_ur=challenge_js_url.replace("token","captcha").replace("challenge.js","captcha.js")
                results['captcha_url']=captcha_js_ur
            solution = get_captcha_aws(results)
            if solution is not None:

                captcha_voucher = solution["captcha_voucher"]
                existing_token = solution["existing_token"]
                print(captcha_voucher)
                print(existing_token)
                results["solution"] = solution

            # 调input
            #https://e6f866fdf351.cebb32b1.ap-northeast-1.token.awswaf.com/e6f866fdf351/a317c00f5699/0d269e2885c2/inputs?client=browser
            input_url = challenge_js_url.replace('challenge.js','inputs?client=browser')
            domain ,path = split_url(input_url)
            headers["authority"]=domain
            headers["path"]=path

            res = requests.Session().get(input_url, proxies=proxies, headers=headers, verify=False)
            json_data = json.loads(res.text)
            results["inputs_result"] = json_data
            # problem
            #https://e6f866fdf351.cebb32b1.ap-northeast-1.captcha.awswaf.com/e6f866fdf351/a317c00f5699/0d269e2885c2/problem?kind=visual&domain=manatuku.com&locale=zh-cn
            captcha_url :str = results['captcha_url']
            problem_url = captcha_url.replace("captcha.js","problem?kind=visual&domain=manatuku.com&locale=zh-cn")
            domain,path = split_url(problem_url)
            headers["authority"] = domain
            headers["path"] = path
            res = requests.Session().get(problem_url, proxies=proxies, headers=headers, verify=False)
            json_data = json.loads(res.text)

            problem_type = json_data['problem_type']
            state = json_data['state']
            key = json_data['key']
            hmac_tag = json_data['hmac_tag']
            validity_duration = json_data['validity_duration']
            results['problem_type']=problem_type
            results['state']=state
            results['hmac_tag']=hmac_tag
            results['validity_duration']=validity_duration
            results['key']=key
            assets = json_data['assets']
            images = json.loads(assets)

            question = images['target']
            imgs = images['images']
            questions= json.loads(question)
            img_list = json.loads(imgs)
            objects = get_api_captcha(img_list,questions)
            verify_url = results["challenge_js_url"].replace("challenge.js","verify")





if __name__ == '__main__':
    get_human_validate()